﻿Imports System.Drawing.Imaging
Imports Microsoft.DirectX
Imports Microsoft.DirectX.Direct3D
''' <summary>
''' Texte die momentan auf dem Bildschirm zu lesen sind
''' </summary>
''' <remarks></remarks>
Public Class ObjektText
    Public Text() As String = {}
    Dim ZuSchreibenderText() As String = {}
    Public XStart As Integer
    Public YStart As Integer
    ''' <summary>
    ''' Direct3D Font Objekt
    ''' </summary>
    ''' <remarks></remarks>
    Dim Farben() As Color = {}
    Public Function GetFarben() As Color()
        Return Farben
    End Function
    Dim Schriftgröße As Integer
    Dim Schreiben As Boolean = False
    Dim Zeile As Integer = 0
    Dim Textstelle As Integer = 0
    Dim TextAbstand As Integer = 0
    Dim Textart As Integer
    Public Function GetSchriftart() As Direct3D.Font
        Return Schriftengine.Fonts(Textart).Schrift
    End Function

    Private Function CreateSchriftart(ByVal neueSchriftart As String, ByVal neueSchriftgröße As Integer, ByVal Stil As System.Drawing.FontStyle) As Boolean
        Dim NeuTextart As String = neueSchriftart + neueSchriftgröße.ToString
        For I = 0 To Schriftengine.Fonts.Length - 1
            If Schriftengine.Fonts(I).Schriftart = NeuTextart Then
                Textart = I
                Return True
            End If
        Next
        Dim systemfont As System.Drawing.Font
        Array.Resize(Schriftengine.Fonts, Schriftengine.Fonts.Length + 1)
        'System Font holen
        systemfont = New System.Drawing.Font(neueSchriftart, neueSchriftgröße, Stil, GraphicsUnit.Pixel)
        'Font Objekt erzeugen
        Schriftengine.Fonts(Schriftengine.Fonts.Length - 1) = New Schriftengine.Font(New Direct3D.Font(Grafikengine.Grafikkarte, systemfont), NeuTextart)
        Textart = Schriftengine.Fonts.Length - 1
        systemfont.Dispose()
        Schriftgröße = neueSchriftgröße
    End Function
    Public Sub New(ByVal neuText() As String, ByVal X As Integer, ByVal Y As Integer, ByVal neueFarben() As Color, ByVal neueSchriftart As String, ByVal neuSchriftgröße As Integer, ByVal Stil As System.Drawing.FontStyle, Optional ByVal neuSchreiben As Boolean = False, Optional ByVal neuTextAbstand As Integer = 3)
        CreateSchriftart(neueSchriftart, neuSchriftgröße, Stil)
        neuerText(neuText, X, Y, neueFarben, neuSchreiben)
        TextAbstand = neuTextAbstand
    End Sub
    Public Sub neuerText(ByVal neuerText() As String, ByVal StartX As Integer, ByVal StartY As Integer, ByVal Textfarben() As Color, Optional ByVal neuSchreiben As Boolean = False, Optional ByVal neuerTextabstand As Integer = 3)
        TextAbstand = neuerTextabstand
        XStart = StartX
        YStart = StartY
        Farben = Textfarben
        Schreiben = neuSchreiben
        If Schreiben = False Then
            Text = neuerText
        Else
            ZuSchreibenderText = neuerText
        End If
    End Sub
    Public Function Malen(ByVal Sprite As Direct3D.Sprite) As Boolean
        If Schreiben = True Then
            If Text.Length = 0 Then Array.Resize(Text, 1)
            Textstelle += 1
            Dim Zeilemom As String = ZuSchreibenderText(Zeile)
            If Textstelle >= Zeilemom.Count Then
                Text(Zeile) = ZuSchreibenderText(Zeile)
                Textstelle = 0
                Zeile += 1
                If Zeile >= ZuSchreibenderText.Length Then
                Else
                    Array.Resize(Text, Text.Length + 1)
                End If
            Else
                If ZuSchreibenderText(Zeile) = "" Then
                    Text(Zeile) = " "
                Else
                    Text(Zeile) = ZuSchreibenderText(Zeile).Remove(Textstelle)
                End If
            End If
        End If
        Dim Schriftart As Direct3D.Font = GetSchriftart()
        Dim Höhe As Integer
        SyncLock Sprite
            If Text.Length > 0 Then
                Höhe = Schriftart.MeasureString(Sprite, Text(0), DrawTextFormat.None, Color.Black).Height
            End If
        End SyncLock
        For I = 0 To Text.Length - 1
            Dim Farbe As Color = Color.Black
            If IsNothing(Farben) = False Then
                If Farben.Length = 1 Then
                    Farbe = Farben(0)
                Else
                    Farbe = Farben(I)
                End If
            End If
            Schriftart.DrawText(Sprite, Text(I), XStart, YStart + I * (Höhe + TextAbstand), Farbe)
        Next
        If Zeile >= ZuSchreibenderText.Length Or Schreiben = False Then
            Zeile = 0
            Schreiben = False
            Return False
        End If
        Return True
    End Function
    Public Sub FertigGeschrieben()
        Schreiben = False
        Text = ZuSchreibenderText
    End Sub
    Public Function IsGeschrieben() As Boolean
        Return Not Schreiben
    End Function
    Public Shared Function getStringsZeilenweise(ByVal S() As String, ByVal Schriftart As Font, ByVal TextBreite As Integer) As String()
        Dim L As New List(Of String)
        For I = 0 To S.Length - 1
            Dim D() As String = getStringsZeilenweise(S(I), Schriftart, TextBreite)
            For I2 = 0 To D.Length - 1
                L.Add(D(I2))
            Next
        Next
        Return L.ToArray
    End Function
    Public Shared Function getStringsZeilenweise(ByVal Text As String, ByVal Schriftart As Font, ByVal TextBreite As Integer) As String()
        If Text.Contains(Environment.NewLine) Then
            Dim Txte() As String = Text.Split(Environment.NewLine)
            Dim ZeilenZusammen() As String = {}
            For i = 1 To Txte.Length - 1
                Txte(i) = Txte(i).Remove(0, 1)
            Next
            For Each Txt In Txte
                For Each Line In getStringsZeilenweise(Txt, Schriftart, TextBreite)
                    Array.Resize(ZeilenZusammen, ZeilenZusammen.Length + 1)
                    ZeilenZusammen(ZeilenZusammen.Length - 1) = Line
                Next
            Next
            Return ZeilenZusammen
        End If
        If Text.Length <= 0 Then Return New String() {Text}
        Dim TextTeile() As String = Text.Split(" ")
        Dim Zeilen() As String = {""}
        Dim WortIndAnfang As Integer = 0
        Dim WortIndEnde As Integer = 0
        While WortIndAnfang < TextTeile.Length
            WortIndEnde = WortIndAnfang
            Dim s As String = ""
            If getWörterBreite(TextTeile, WortIndAnfang, WortIndEnde, Schriftart) <= TextBreite Then
                'zumindest ein Wort ist OK 
                'mal schauen, wie weit wir es treiben können 
                Do While getWörterBreite(TextTeile, WortIndAnfang, WortIndEnde, Schriftart) <= TextBreite
                    WortIndEnde += 1
                    If WortIndEnde > TextTeile.Length - 1 Then
                        'ups, das war vielleicht ein bischen viel.
                        Exit Do
                    End If
                Loop
                WortIndEnde -= 1 'das war wohl eins zu viel 

                If WortIndEnde > WortIndAnfang Then
                    For i2 = WortIndAnfang To WortIndEnde - 1
                        s += TextTeile(i2) + " "
                    Next
                    s += TextTeile(WortIndEnde)   'NICHT ANFANG
                Else
                    s = TextTeile(WortIndAnfang)
                End If

                Zeilen(Zeilen.Length - 1) = s
                Array.Resize(Zeilen, Zeilen.Length + 1)
            Else
                'Wenn nichtmal ein Wort geht, müssen wir halt das doch aufteilen, da ich aber keine silbentrennung machen will (das dauert glaub ich doch zu lange)(zum coden ) werden einfach die buchstaben abgetrennt, die zuviel sind!
                'na dann eben das ganze Char für Char
                'aber am besten rückwärts, da ja vermutlich dieser Fall eher für lange Wörter zutrifft, und die schneidet wan vermutlich besser ab!
                Dim RestWort As String = TextTeile(WortIndAnfang)
                While RestWort.Length > 0
                    Dim Wort As String = RestWort
                    Do While getTextBreite(Wort, Schriftart) > TextBreite
                        'Das Wort ist immer noch zu groß
                        Wort = Wort.Remove(Wort.Length - 1)
                        If Wort.Length <= 1 Then
                            'Oha! Jetzt ist wirklich nicht mehr viel von dem Wort übrig!
                            'Was machen wir jetzt mit dem einen Buchstaben?
                            'am besten einfach trotzdem reinschreiben.
                            Exit Do
                        End If
                    Loop
                    Zeilen(Zeilen.Length - 1) = Wort
                    Array.Resize(Zeilen, Zeilen.Length + 1)
                    RestWort.Remove(0, Wort.Length)
                End While
            End If

            WortIndAnfang = WortIndEnde + 1
        End While
        Array.Resize(Zeilen, Zeilen.Length - 1) 'eine ist ja zuviel
        Return Zeilen
    End Function
    Private Shared Function getWörterBreite(ByVal Wörter() As String, ByVal WortIndAnfang As Integer, ByVal WortIndEnde As Integer, ByVal Schriftart As Font) As Integer
        Dim s As String = ""
        If WortIndEnde > WortIndAnfang Then
            For i = WortIndAnfang To WortIndEnde - 1
                s += Wörter(i) + " "
            Next
            s += Wörter(WortIndEnde)
        Else
            s = Wörter(WortIndAnfang)
        End If
        Return getTextBreite(s, Schriftart)
    End Function
    Private Shared Function getTextBreite(ByVal Text As String, ByVal Schriftart As Font) As Integer
        Return Schriftart.MeasureString(Schriftengine.Sprite2, Text, DrawTextFormat.None, Color.Blue).Width
    End Function
End Class
